package com.yunmaozj.tools.site.server.util;

import com.yunmaozj.tools.site.server.dto.Developer;
import com.yunmaozj.tools.site.server.dto.DocsList;
import lombok.NonNull;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.dom4j.tree.DefaultElement;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static java.util.Collections.EMPTY_LIST;
import static java.util.Objects.isNull;

/**
 * @author zhongminghong
 * @email zhongmh@yunmaozj.com
 * @create 2022-05-28 11:39
 */
public class SiteMetadata {

    private final Document document;
    private final File siteMetadataFile;

    public SiteMetadata(Document document, File siteMetadataFile) {
        this.document = document;
        this.siteMetadataFile = siteMetadataFile;
    }

    public boolean existsUser(@NonNull String username, @NonNull String password) {
        Element element = document.getRootElement();
        element = element.element("users");
        if (isNull(element)) {
            return false;
        }
        element = element.element(username);
        if (isNull(element)) {
            return false;
        }
        return StringUtils.equals(password, element.attributeValue("password"));
    }

    public boolean existsDeveloper(String username, String password) {
        Element element = document.getRootElement();
        element = element.element("developers");
        if (isNull(element)) {
            return false;
        }
        element = element.element(username);
        if (isNull(element)) {
            return false;
        }
        return StringUtils.equals(password, element.attributeValue("password"));
    }

    public void addProject(List<Developer> developers, String projectId) {
        Element element = document.getRootElement();
        element = element.element("developers");
        for (Developer developer : developers) {
            Element developerElement = element.element(developer.getId());
            if (isNull(developerElement)) {
                developerElement = new DefaultElement(developer.getId());
                developerElement.attributeValue("password","123456");
                element.add(developerElement);
            }
            Element projectElement = developerElement.element(projectId);
            if (isNull(projectElement)) {
                developerElement.add(new DefaultElement(projectId) {{
                    addAttribute("latestModifyTime", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                }});
            } else {
                projectElement.attributeValue("latestModifyTime", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            }
        }
        writeMetadataFile(siteMetadataFile, document);
    }

    public List<DocsList> projectList(String developerName) {
        Element element = document.getRootElement();
        element = element.element("developers");
        if (isNull(element)) {
            return EMPTY_LIST;
        }
        element = element.element(developerName);
        if (isNull(element)) {
            return EMPTY_LIST;
        }
        List<Element> projects = element.elements();
        if (isNull(projects)) {
            return EMPTY_LIST;
        }

        return projects.stream().map(e -> new DocsList(e.getName(), e.attributeValue("latestModifyTime"))).collect(Collectors.toList());
    }


    public static SiteMetadata load(FileManager fileManager) throws DocumentException {
        File siteMetadataFile = new File(fileManager.getRootDirectory(), "site-metadata.xml");
        synchronized (SiteMetadata.class) {
            if (!siteMetadataFile.exists()) {
                initSiteMetadataFile(siteMetadataFile);
            }
        }
        SAXReader reader = new SAXReader();
        Document document = reader.read(siteMetadataFile);
        return new SiteMetadata(document, siteMetadataFile);
    }

    public static void initSiteMetadataFile(File siteMetadataFile) {
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("site");
        root.addAttribute("addTime", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        Element users = new DefaultElement("users");
        root.add(users);
        users.add(new DefaultElement("admin") {{
            addAttribute("password", "123456");
        }});
        writeMetadataFile(siteMetadataFile, doc);
    }

    private static void writeMetadataFile(File metadataFile, Document document) {
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");
        Writer out = null;
        try {
            out = new FileWriter(metadataFile);
            XMLWriter writer = new XMLWriter(out, format);
            writer.write(document);
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(out);
        }
    }
}
